package com.bt.springboot.common.aspect;

import cn.hutool.core.util.StrUtil;
import com.bt.springboot.common.annotation.NoRepeatSubmit;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

/**
 * @author zkx
 * @Date 2023/10/30 13:29
 */
@Aspect
@Component
public class NoRepeatSubmitAspect {

	@Autowired
	private RedisTemplate<String, String> redisTemplate;

	@Pointcut("@annotation(com.bt.springboot.common.annotation.NoRepeatSubmit)")
	public void noRepeatSubmit() {
	}

	@Around("noRepeatSubmit()")
	public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
		ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
		HttpServletRequest request = attributes.getRequest();
		String token = request.getHeader("token");
		if (StrUtil.isEmpty(token)){
			throw new RuntimeException("token不能为空");
		}
		String path = request.getServletPath();
		String key = "NoRepeatSubmit:" + token + ":" + path;
		boolean isExist = redisTemplate.hasKey(key);
		if (isExist){
			throw new RuntimeException("请勿重复提交");
		}
		redisTemplate.opsForValue().set(key,"0",expireTime(joinPoint), TimeUnit.SECONDS);
		return joinPoint.proceed();
	}

	/**
	 * 获取注解中的过期时间
	 * @return
	 */
	private int expireTime(ProceedingJoinPoint joinPoint){
		MethodSignature signature = (MethodSignature) joinPoint.getSignature();
		Method method = signature.getMethod();
		NoRepeatSubmit annotation = method.getAnnotation(NoRepeatSubmit.class);
		return annotation.expireTime();
	}
}
